package cn.kennylee.codehub.springboot.microtrace.dubbo;

import cn.kennylee.codehub.springboot.microtrace.TraceContext;
import cn.kennylee.codehub.springboot.microtrace.TraceUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.*;
import org.slf4j.MDC;
import org.springframework.util.StringUtils;

import static cn.kennylee.codehub.springboot.microtrace.TraceUtils.getMdcTraceIdName;

/**
 * * Dubbo提供者链路追踪过滤器
 * <p>Created on 2025/5/7.</p>
 *
 * @author kennylee
 * @since 0.0.1
 */
@Activate(group = CommonConstants.PROVIDER, order = -10000)
@Slf4j
public class DubboTraceProviderFilter implements Filter {

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {

        if (TraceUtils.hasTraceId()) {
            // 如果已经存在 Trace ID，则直接继续处理请求
            log.warn("已经存在 Trace ID: {}", MDC.get(getMdcTraceIdName()));
            return invoker.invoke(invocation);
        }

        // 从Dubbo隐式参数初始化Trace上下文
        TraceContext.initFromRpcContext(invocation);

        if (!StringUtils.hasLength(TraceContext.getTraceId())) {
            log.warn("找不到 Trace ID，可能是因为没有设置 Dubbo 隐式参数");
            return invoker.invoke(invocation);
        }

        try {
            log.trace("设置 Trace ID: {}", TraceContext.getTraceId());
            MDC.put(getMdcTraceIdName(), TraceContext.getTraceId());
            return invoker.invoke(invocation);
        } finally {
            TraceContext.clear();
        }
    }
}
